package com.android.universydroid.framework;

import java.lang.reflect.Field;
import java.util.Map.Entry;
import java.util.Set;

import com.android.universydroid.view.Splash;

import android.content.ContentValues;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.widget.Toast;

public class DALBase {

	private DBHelper _dbHelper;

	public DALBase(Context c) {
		_dbHelper = new DBHelper(c);
	}

	// Executa o SQL sem conexao
	public long Execute(BaseTO to, SQLType sqlType) {
		SQLiteDatabase db = _dbHelper.getWritableDatabase();
		try {
			return this.Execute(to, sqlType, db);
		} finally {
			db.close();
		}
	}

	// Executa um SQL generico de acordo com o TO passado e o tipo de SQL a ser
	// executado.
	public long Execute(BaseTO to, SQLType sqlType, SQLiteDatabase connection) {
		String tableName = "";
		long result = -1;

		if (to.getClass().isAnnotationPresent(Table.class)) {
			Table tableMetadata = to.getClass().getAnnotation(Table.class);
			tableName = tableMetadata.name();
			if (sqlType.equals(SQLType.DELETE)
					|| sqlType.equals(SQLType.INSERT)
					|| sqlType.equals(SQLType.UPDATE))
				result = this.ResolveScalarSql(tableName, sqlType, connection,
						to);
			// else
		}

		return result;

	}

	// Resolve o modelo basico do SQL de acordo com o tipo.
	protected long ResolveScalarSql(String tableName, SQLType sqlType,
			SQLiteDatabase connection, BaseTO to) {
		long result = -1;
		String erro = "";
		try {
			switch (sqlType) {
			case DELETE:
				result = connection.delete(tableName, this.GetFilledFields(this.ResolveParams(to, sqlType, true)),
						null);
				break;
			case INSERT:
				result = connection.insertOrThrow(tableName, null, this.ResolveParams(to, sqlType, false));
				break;
			case UPDATE:
				result = connection
						.update(tableName, this.ResolveParams(to, sqlType, false), this.GetFilledFields(this
								.ResolveParams(to, sqlType, true)), null);
				break;
			}
		}
		catch (SQLException ex) {
			erro = ex.getMessage();
		}
		
		return result;
	}

	protected String GetFilledFields(ContentValues params) {
		String clause = "";
		Set<Entry<String, Object>> s = params.valueSet();
		for (Entry<String, Object> entry : s) {
			clause += entry.getKey() + " = '" + entry.getValue().toString()
					+ "', ";
		}
		if (clause.length() > 0)
			clause.substring(0, clause.lastIndexOf(", ") - 1);

		return clause;
	}

	// Monta array com os parametros a serem setados no SQL.
	protected ContentValues ResolveParams(BaseTO to, SQLType sqlType,
			boolean primaryKeys) {
		Field[] toFields = to.getClass().getFields();
		ContentValues params = new ContentValues();
		for (Field currentField : toFields) {
			try {
				if (currentField.isAnnotationPresent(TableField.class)) {
					TableField fieldMetadata = currentField
							.getAnnotation(TableField.class);
					if (fieldMetadata.isPrimaryKey() == primaryKeys) {
						if (fieldMetadata.type().equals(TableFieldType.TEXT)) {
							if (!currentField.get(to).equals(null)) {
								params.put(fieldMetadata.name(), currentField
										.get(to).toString());
							}
						} else if (fieldMetadata.type().equals(
								TableFieldType.NUMBER)) {
							if (!currentField.get(to).equals(null)) {
								params.put(fieldMetadata.name(), Integer
										.parseInt(currentField.get(to)
												.toString()));
							}
						}
					}
				}
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return params;
	}
}
